<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
	<title>function_score (函数评分) 查询 | ElasticSearch 7.7 权威指南中文版</title>
	<meta name="keywords" content="ElasticSearch 权威指南中文版, elasticsearch 7, es7, 实时数据分析，实时数据检索" />
    <meta name="description" content="ElasticSearch 权威指南中文版, elasticsearch 7, es7, 实时数据分析，实时数据检索" />
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
	<link rel="stylesheet" type="text/css" href="../static/styles.css" />
	<script>
	var _link = 'query-dsl-function-score-query.html';
    </script>
</head>
<body>
<div class="main-container">
    <section id="content">
        <div class="content-wrapper">
            <section id="guide" lang="zh_cn">
                <div class="container">
                    <div class="row">
                        <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                            <div style="color:gray; word-break: break-all; font-size:12px;">原英文版地址: <a href="https://www.elastic.co/guide/en/elasticsearch/reference/7.7/query-dsl-function-score-query.html" rel="nofollow" target="_blank">https://www.elastic.co/guide/en/elasticsearch/reference/7.7/query-dsl-function-score-query.html</a>, 原文档版权归 www.elastic.co 所有<br/>本地英文版地址: <a href="../en/query-dsl-function-score-query.html" rel="nofollow" target="_blank">../en/query-dsl-function-score-query.html</a></div>
                        <!-- start body -->
                  <div class="page_header">
<strong>重要</strong>: 此版本不会发布额外的bug修复或文档更新。最新信息请参考 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html" rel="nofollow">当前版本文档</a>。
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch 权威指南 [7.7]</a></span>
»
<span class="breadcrumb-link"><a href="query-dsl.html">查询领域特定语言(Query DSL)</a></span>
»
<span class="breadcrumb-link"><a href="compound-queries.html">复合查询</a></span>
»
<span class="breadcrumb-node">function_score (函数评分) 查询</span>
</div>
<div class="navheader">
<span class="prev">
<a href="query-dsl-dis-max-query.html">« dis_max 查询</a>
</span>
<span class="next">
<a href="full-text-queries.html">全文查询 »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="query-dsl-function-score-query"></a>function_score (函数评分) 查询
</h2>
</div></div></div>

<p>
<code class="literal">function_score</code> 允许你修改查询检索到的文档的分数。  

例如，如果一个评分函数的计算开销很大，并且它足以计算经过筛选的一组文档的分数，那么这就很有用了。  
</p>
<p>
要使用 <code class="literal">function_score</code>，用户必须定义一个查询和一个或多个函数，这些函数为查询返回的每个文档计算一个新分数。  
</p>
<p>
<code class="literal">function_score</code> 只能用于一个函数，如下所示：
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "query": {
        "function_score": {
            "query": { "match_all": {} },
            "boost": "5",
            "random_score": {}, <a id="CO36-1"></a><i class="conum" data-value="1"></i>
            "boost_mode":"multiply"
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/100.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO36-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>受支持的函数列表请参考 <a class="xref" href="query-dsl-function-score-query.html#score-functions">函数评分</a>。</p>
</td>
</tr>
</table>
</div>
<p>
此外，几个功能可以组合。在这种情况下，我们可以选择只在文档匹配指定的 filter 查询时应用该函数。  
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "query": {
        "function_score": {
          "query": { "match_all": {} },
          "boost": "5", <a id="CO37-1"></a><i class="conum" data-value="1"></i>
          "functions": [
              {
                  "filter": { "match": { "test": "bar" } },
                  "random_score": {}, <a id="CO37-2"></a><i class="conum" data-value="2"></i>
                  "weight": 23
              },
              {
                  "filter": { "match": { "test": "cat" } },
                  "weight": 42
              }
          ],
          "max_boost": 42,
          "score_mode": "max",
          "boost_mode": "multiply",
          "min_score" : 42
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/101.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO37-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>整个查询的提高(boost)。</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO37-2"><i class="conum" data-value="2"></i></a></p>
</td>
<td align="left" valign="top">
<p>受支持的函数列表请参考 <a class="xref" href="query-dsl-function-score-query.html#score-functions">函数评分</a>。</p>
</td>
</tr>
</table>
</div>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>每个函数的 filter 查询产生的分数并不重要。</p>
</div>
</div>
<p>
如果函数中没有给出任何 filter，这相当于指定 <code class="literal">"match_all": {}</code>。  
</p>
<p>
首先，每个文档由定义的函数评分。  
参数 <code class="literal">score_mode</code> 指定如何组合计算出的分数： 
</p>
<div class="informaltable">
<table border="0" cellpadding="4px">
<colgroup>
<col>
<col>
</colgroup>
<tbody valign="top">
<tr>
<td valign="top">
<p>
<code class="literal">multiply</code>
</p>
</td>
<td valign="top">
<p>
分数相乘（默认）
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">sum</code>
</p>
</td>
<td valign="top">
<p>
分数相加，求和
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">avg</code>
</p>
</td>
<td valign="top">
<p>
分数的平均值
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">first</code>
</p>
</td>
<td valign="top">
<p>
应用第一个具有匹配 filter 的函数
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">max</code>
</p>
</td>
<td valign="top">
<p>
取分数最大值
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">min</code>
</p>
</td>
<td valign="top">
<p>
取分数最小值
</p>
</td>
</tr>
</tbody>
</table>
</div>
<p>
因为分数可以在不同的范围内(例如，衰减函数<span class="remark">(decay function)</span>在0到1之间，而 <code class="literal">field_value_factor</code> 是任意的)，而且有时函数对分数的不同影响是可取的，所以可以使用用户定义的 <code class="literal">weight</code>(权重) 来调整每个函数的分数。  

<code class="literal">weight</code>可以在 <code class="literal">functions</code>数组(上面的例子)中按每个函数定义，并与相应函数计算的分数相乘。 


如果给定 weight 时没有任何其他函数声明，<code class="literal">weight</code> 就会作为一个函数返回<code class="literal">weight</code> 。  
</p>
<p>
如果 <code class="literal">score_mode</code> 被设置为 <code class="literal">avg</code>，则单个分数将被 <span class="strong strong"><strong>weighted(加权)</strong></span> 平均。  

例如，如果两个函数返回 1 和 2 分，它们各自的权重分别为 3 和 4，那么它们的得分将合并为 <code class="literal">(1*3+2*4)/(3+4)</code> 而<span class="strong strong"><strong>不是</strong></span> <code class="literal">(1*3+2*4)/2</code>。  
</p>
<p>
通过设置 <code class="literal">max_boost</code> 参数，可以限制新的分数不超过某个限制。

<code class="literal">max_boost</code> 的默认值是 FLT_MAX。
</p>
<p>
新计算的分数与查询的分数相结合。 参数 <code class="literal">boost_mode</code> 定义了如何操作：
</p>
<div class="informaltable">
<table border="0" cellpadding="4px">
<colgroup>
<col>
<col>
</colgroup>
<tbody valign="top">
<tr>
<td valign="top">
<p>
<code class="literal">multiply</code>
</p>
</td>
<td valign="top">
<p>
查询分数和函数分数相乘（默认）
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">replace</code>
</p>
</td>
<td valign="top">
<p>
只使用函数分数，而忽略查询分数
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">sum</code>
</p>
</td>
<td valign="top">
<p>
查询分数和函数分数相加
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">avg</code>
</p>
</td>
<td valign="top">
<p>
平均值
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">max</code>
</p>
</td>
<td valign="top">
<p>
查询分数和函数分数的最大值
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">min</code>
</p>
</td>
<td valign="top">
<p>
查询分数和函数分数的最小值
</p>
</td>
</tr>
</tbody>
</table>
</div>
<p>
默认情况下，修改分数不会改变匹配的文档。  

要排除不满足某个分数阈值的文档，可以将参数 <code class="literal">min_score</code> 设置为所需的分数阈值。  
</p>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>
要让 <code class="literal">min_score</code> 起作用，需要对查询返回的<span class="strong strong"><strong>所有</strong></span>文档进行评分，然后逐一过滤掉。
</p>
</div>
</div>
<p>
<a id="score-functions"></a>
<code class="literal">function_score</code> 查询提供了以下几种评分函数。
</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<a class="xref" href="query-dsl-function-score-query.html#function-script-score" title="Script score"><code class="literal">script_score</code></a>
</li>
<li class="listitem">
<a class="xref" href="query-dsl-function-score-query.html#function-weight" title="Weight"><code class="literal">weight</code></a>
</li>
<li class="listitem">
<a class="xref" href="query-dsl-function-score-query.html#function-random" title="Random"><code class="literal">random_score</code></a>
</li>
<li class="listitem">
<a class="xref" href="query-dsl-function-score-query.html#function-field-value-factor" title="Field Value factor"><code class="literal">field_value_factor</code></a>
</li>
<li class="listitem">
<a class="xref" href="query-dsl-function-score-query.html#function-decay" title="Decay functions">衰减函数 (decay function)</a>: <code class="literal">gauss</code>, <code class="literal">linear</code>, <code class="literal">exp</code>
</li>
</ul>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="function-script-score"></a>脚本评分 (Script score)
</h3>
</div></div></div>
<p>
<code class="literal">script_score</code> 函数允许包裹另一个查询，并使用脚本表达式使用从文档中的其他 数值(numeric) 字段值派生的计算定制该查询的评分。 

这里是一个简单的例子:
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "query": {
        "function_score": {
            "query": {
                "match": { "message": "elasticsearch" }
            },
            "script_score" : {
                "script" : {
                  "source": "Math.log(2 + doc['likes'].value)"
                }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/102.console"></div>
<div class="important admon">
<div class="icon"></div>
<div class="admon_content">
<p>
在 Elasticsearch 中，所有文档的评分都是一个 32 位的浮点数。  
</p>
<p>
如果 <code class="literal">script_score</code> 函数生成了一个精度更高的分数，那么它将被转换为最接近的 32 位浮点数。  
</p>
<p>
同样，分数必须是非负的。 否则，Elasticsearch 返回一个错误。  
</p>
</div>
</div>
<p>
在不同的脚本字段值和表达式之上，可以使用 <code class="literal">_score</code> 脚本参数根据包裹的查询来检索分数。  
</p>
<p>
脚本编译被缓存以更快地执行。  

如果脚本有需要考虑的参数，最好重用同一个脚本，并为其提供 <code class="literal">params</code>(参数):
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "query": {
        "function_score": {
            "query": {
                "match": { "message": "elasticsearch" }
            },
            "script_score" : {
                "script" : {
                    "params": {
                        "a": 5,
                        "b": 1.2
                    },
                    "source": "params.a / Math.pow(params.b, doc['likes'].value)"
                }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/103.console"></div>
<p>
请注意，与 <code class="literal">custom_score</code> 查询不同，查询的分数会乘以脚本评分的结果。

如果你希望禁止这种情况，请设置 <code class="literal">"boost_mode": "replace"</code>。
</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="function-weight"></a>权重 (weight)
</h3>
</div></div></div>
<p>
<code class="literal">weight</code> 分数允许你将分数乘以指定的 <code class="literal">weight</code> 值。

这有时是需要的，因为在特定查询上设置的 boost(提升)值 被归一化了，而对于这个评分函数却没有。

number 值的类型是 float。
</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"weight" : number</pre>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="function-random"></a>随机 (random)
</h3>
</div></div></div>
<p>
<code class="literal">random_score</code> 生成从 0 到 1 (不包括1) 均匀分布的分数。

默认情况下，它使用内部 Lucene 文档 id 作为随机数种子(seed)，这非常有效，但不幸的是不可再现的，因为文档可能会被合并而重新编号。
</p>
<p>
如果你希望分数是可再现的，可以提供一个 <code class="literal">seed</code><span class="remark">(种子)</span> 和 <code class="literal">field</code><span class="remark">(字段)</span>。

然后，将基于该种子、所考虑文档的 <code class="literal">field</code><span class="remark">(字段)</span> 的最小值以及基于索引名称和分片id计算的 盐(salt) 来计算最终得分，以便具有相同值但存储在不同索引中的文档获得不同的得分。

请注意，在同一个分片中并且具有相同 <code class="literal">field</code> 值的文档将获得相同的分数，因此通常希望对所有文档使用具有唯一值的字段。

一个好的默认选择可能是使用 <code class="literal">_seq_no</code> 字段，其唯一的缺点是如果文档被更新，分数将会改变，因为更新操作也会更新 <code class="literal">_seq_no</code> 字段的值。
</p>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>
可以在不设置字段的情况下设置种子，但这已被废弃，因为这需要在 <code class="literal">_id</code> 字段上加载 fielddata(字段的数据)，这会消耗大量内存。
</p>
</div>
</div>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "query": {
        "function_score": {
            "random_score": {
                "seed": 10,
                "field": "_seq_no"
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/104.console"></div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="function-field-value-factor"></a>字段值因子 (field value factor)
</h3>
</div></div></div>
<p>
<code class="literal">field_value_factor</code> 函数允许你使用文档中的字段来影响分数。

它类似于使用 <code class="literal">script_score</code> 函数，但是它避免了脚本的开销。

如果用于 多值(multi-valued) 字段，则计算中仅使用字段的第一个值。
</p>
<p>
例如，假设你有一个用数字 <code class="literal">likes</code> 字段索引的文档，并希望用该字段影响文档的评分，以下就是一个示例：
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "query": {
        "function_score": {
            "field_value_factor": {
                "field": "likes",
                "factor": 1.2,
                "modifier": "sqrt",
                "missing": 1
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/105.console"></div>
<p>
上面的代码将转化为以下评分公式：
</p>
<p><code class="literal">sqrt(1.2 * doc['likes'].value)</code></p>
<p>
函数 <code class="literal">field_value_factor</code> 有多个选项：
</p>
<div class="informaltable">
<table border="0" cellpadding="4px">
<colgroup>
<col>
<col>
</colgroup>
<tbody valign="top">
<tr>
<td valign="top">
<p>
<code class="literal">field</code>
</p>
</td>
<td valign="top">
<p>
要从文档中提取的字段。
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">factor</code>
</p>
</td>
<td valign="top">
<p>
与字段值相乘的可选因子，默认值为 <code class="literal">1</code>。
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">modifier</code>
</p>
</td>
<td valign="top">
<p>
应用于字段值的修饰符，可以是下列值之一：<code class="literal">none</code>、<code class="literal">log</code>、<code class="literal">log1p</code>、<code class="literal">log2p</code>、<code class="literal">ln</code>、<code class="literal">ln1p</code>、<code class="literal">ln2p</code>、<code class="literal">square</code>、<code class="literal">sqrt</code> 或 <code class="literal">reciprocal</code>。

默认值为 <code class="literal">none</code>。
</p>
</td>
</tr>
</tbody>
</table>
</div>
<div class="informaltable">
<table border="1" cellpadding="4px">
<colgroup>
<col class="col_1">
<col class="col_2">
</colgroup>
<thead>
<tr>
<th align="left" valign="top">修饰符</th>
<th align="left" valign="top">意义</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left" valign="top"><p><code class="literal">none</code></p></td>
<td align="left" valign="top"><p>
不要对字段值应用任何乘数
</p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">log</code></p></td>
<td align="left" valign="top">
<p>
取字段值的<a href="https://en.wikipedia.org/wiki/Common_logarithm" class="ulink" target="_top" rel="nofollow">常用对数(common logarithm)</a> 。

由于该函数用于 0 到 1 之间的值时会返回负值，这会导致错误，所以建议使用 <code class="literal">log1p</code> 以代替之。
</p>
</td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">log1p</code></p></td>
<td align="left" valign="top"><p>
将字段值加 1，取常用对数
</p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">log2p</code></p></td>
<td align="left" valign="top"><p>
将字段值加 2，取常用对数
</p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">ln</code></p></td>
<td align="left" valign="top">
<p>
取字段值的<a href="https://en.wikipedia.org/wiki/Natural_logarithm" class="ulink" target="_top">自然对数(natural logarithm)</a>。

由于该函数用于 0 到 1 之间的值时会返回负值，这会导致错误，因此建议使用 <code class="literal">ln1p</code> 以代替之。
</p>
</td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">ln1p</code></p></td>
<td align="left" valign="top"><p>
将字段值加 1，取自然对数
</p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">ln2p</code></p></td>
<td align="left" valign="top"><p>
将字段值加 2，取自然对数
</p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">square</code></p></td>
<td align="left" valign="top"><p>
字段值的平方(乘以它本身)
</p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">sqrt</code></p></td>
<td align="left" valign="top"><p>
取字段值的 <a href="https://en.wikipedia.org/wiki/Square_root" class="ulink" target="_top">平方根(square root)</a>
</p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">reciprocal</code></p></td>
<td align="left" valign="top"><p>
字段值的<a href="https://en.wikipedia.org/wiki/Multiplicative_inverse" class="ulink" target="_top">倒数(reciprocate)</a> ，与 <code class="literal">1/x</code> 相同，其中 <code class="literal">x</code> 是字段的值
</p></td>
</tr>
</tbody>
</table>
</div>
<div class="variablelist">
<dl class="variablelist">
<dt>
<span class="term">
<code class="literal">missing</code>
</span>
</dt>
<dd>
文档没有该字段时使用的值。

修饰符和因子仍然应用于它，就好像它是从文档中读取的一样。
</dd>
</dl>
</div>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>
<code class="literal">field_value_score</code> 函数生成的分数值必须是非负的，否则将会引起错误。

如果 <code class="literal">log</code> 和 <code class="literal">ln</code> 修饰符用于 0 到 1 之间的值，将产生负值。

确保使用范围过滤器限制字段的值以避免这种情况，或者使用 <code class="literal">log1p</code> 和 <code class="literal">ln1p</code>。
</p>
</div>
</div>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>
请记住，取 0 的 log() 或 负数的平方根是非法操作，将会引发异常。

确保使用范围过滤器限制字段的值以避免这种情况，或者使用 <code class="literal">log1p</code> 和 <code class="literal">ln1p</code>。
</p>
</div>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="function-decay"></a>衰减函数 (decay functions)
</h3>
</div></div></div>
<p>
衰减函数(decay functions) 使用根据文档的数值字段值与用户给定原点的距离衰减的函数对文档进行评分。

这类似于 范围查询(range query)，但是使用平滑的边缘而不是方框。
</p>
<p>
要对具有数值字段的查询使用距离评分，用户必须为每个字段定义 <code class="literal">origin</code> <span class="remark">(原点)</span>和 <code class="literal">scale</code><span class="remark">(范围)</span>。

需要使用 <code class="literal">origin</code> <span class="remark">(原点)</span> 来定义计算距离的“中心点”，使用 <code class="literal">scale</code><span class="remark">(范围)</span> 来定义衰减率。

衰减函数可以这样定义：
</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"DECAY_FUNCTION": { <a id="CO38-1"></a><i class="conum" data-value="1"></i>
    "FIELD_NAME": { <a id="CO38-2"></a><i class="conum" data-value="2"></i>
          "origin": "11, 12",
          "scale": "2km",
          "offset": "0km",
          "decay": 0.33
    }
}</pre>
</div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO38-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>
<code class="literal">DECAY_FUNCTION</code> 应为 <code class="literal">linear</code>、<code class="literal">exp</code> 或 <code class="literal">gauss</code>。
</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO38-2"><i class="conum" data-value="2"></i></a></p>
</td>
<td align="left" valign="top">
<p>指定的字段必须是 numeric、date 或 geo-point 类型的。</p>
</td>
</tr>
</table>
</div>
<p>
在上面的例子中，字段是 <a class="xref" href="geo-point.html" title="Geo-point datatype"><code class="literal">geo_point</code></a> 类型，origin 可以以 geo 格式提供。

在这种情况下，<code class="literal">scale</code> 和 <code class="literal">offset</code> 必须使用上例中的单位。

如果你的字段是 date 类型，可以将 <code class="literal">scale</code> 和 <code class="literal">offset</code> 设置为天(d)、周(w)等。

示例：
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "query": {
        "function_score": {
            "gauss": {
                "date": {
                      "origin": "2013-09-17", <a id="CO39-1"></a><i class="conum" data-value="1"></i>
                      "scale": "10d",
                      "offset": "5d", <a id="CO39-2"></a><i class="conum" data-value="2"></i>
                      "decay" : 0.5 <a id="CO39-3"></a><i class="conum" data-value="2"></i>
                }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/106.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO39-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>
origin 的日期格式取决于 mapping 中定义的<a class="xref" href="mapping-date-format.html" title="format"><code class="literal">format</code></a><span class="remark">(格式)</span>。

如果没有定义origin，则使用当前时间。
</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO39-2"><i class="conum" data-value="2"></i></a><a href="#CO39-3"></a></p>
</td>
<td align="left" valign="top">
<p>参数 <code class="literal">offset</code> 和 <code class="literal">decay</code> 是可选的。</p>
</td>
</tr>
</table>
</div>
<div class="informaltable">
<table border="0" cellpadding="4px">
<colgroup>
<col>
<col>
</colgroup>
<tbody valign="top">
<tr>
<td valign="top">
<p>
<code class="literal">origin</code>
</p>
</td>
<td valign="top">
<p>
用于计算距离的原点。

对于 numeric 字段，必须以数字形式给出；对于 date 字段，必须以日期形式给出；对于 geo 段，必须以地理点形式给出。

对于 geo 和 numeric 字段是必需的。

对于 date 字段，默认值为 <code class="literal">now</code><span class="remark">(现在)</span>。

原点支持日期计算(例如 <code class="literal">now-1h</code>)。
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">scale</code>
</p>
</td>
<td valign="top">
<p>
所有类型都需要。

定义从 origin + offset 的距离，在该距离处计算的分数将等于参数 <code class="literal">decay</code>。<br/>

对于 geo 字段：可以定义为 数字 + 单位（如："1km"，"12m"，...)，默认单位是 <code class="literal">m</code> (米)。<br/>

对于 date 字段：可以定义为 数字 + 单位（如："1h"，"10d"...​），默认单位是  <code class="literal">ms</code> (毫秒)。<br/>

对于 numeric 字段: 可以是任意数值。
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">offset</code>
</p>
</td>
<td valign="top">
<p>
如果定义了 <code class="literal">offset</code>，衰减函数将只计算距离大于定义的 <code class="literal">offset</code> 的文档衰减。

默认值为 <code class="literal">0</code>。
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">decay</code>
</p>
</td>
<td valign="top">
<p>
参数 <code class="literal">decay</code> 定义了如何在 <code class="literal">scale</code> 给定的距离上对文档进行评分。

如果没有定义 <code class="literal">decay</code>，则在 <code class="literal">scale</code> 距离上的文档将被评分为 <code class="literal">0.5</code>。
</p>
</td>
</tr>
</tbody>
</table>
</div>
<p>
在第一个例子中，文档可能表示酒店并包含 geo(地理位置) 字段。

你希望根据酒店离给定位置的距离来计算衰减函数。

你可能不会立即看到为 guass(高斯)函数 选择哪一个 scale，但是你可以这样说：“在距离期望位置 2km 处，分数应减少到三分之一。”

然后将自动调整参数"scale"，以确保评分函数计算出距离期望位置 2km 的酒店的分数为0.33。
</p>
<p>
在第二个例子中，字段值在 2013-09-12 和 2013-09-22 之间的文档的权重(weight)为 1.0，距离该日期超过 15 天的文档的权重为 0.5。
</p>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="_supported_decay_functions"></a>支持的衰减函数
</h4>
</div></div></div>
<p><code class="literal">DECAY_FUNCTION</code> 决定衰减的形状：</p>
<div class="variablelist">
<dl class="variablelist">
<dt>
<span class="term">
<code class="literal">gauss</code>
</span>
</dt>
<dd>
<p>正态衰减，计算如下：</p>
<p><span class="image"><img src="../static/images/Gaussian.png" alt="Gaussian"></span></p>
<p>
其中，要计算<span class="image"><img src="../static/images/sigma.png" alt="sigma"></span>以确保分数在距离 <code class="literal">origin</code>+-<code class="literal">offset</code> 的 <code class="literal">scale</code> 距离处取值为 <code class="literal">decay</code>：
</p>
<p><span class="image"><img src="../static/images/sigma_calc.png" alt="sigma calc"></span></p>
<p>有关 <code class="literal">gauss</code> 函数生成的曲线的图形的演示，请参考 <a class="xref" href="query-dsl-function-score-query.html#gauss-decay" title="Normal decay, keyword gauss">正态衰减，关键字 <code class="literal">gauss</code></a>。</p>
</dd>
<dt>
<span class="term">
<code class="literal">exp</code>
</span>
</dt>
<dd>
<p>指数衰减，计算如下：</p>
<p><span class="image"><img src="../static/images/Exponential.png" alt="Exponential"></span></p>
<p>
其中，参数<span class="image"><img src="../static/images/lambda.png" alt="lambda"></span>再次被计算以确保分数在距离 <code class="literal">origin</code>+-<code class="literal">offset</code> 的 <code class="literal">scale</code> 距离处取值为 <code class="literal">decay</code>：
</p>
<p><span class="image"><img src="../static/images/lambda_calc.png" alt="lambda calc"></span></p>
<p>有关 <code class="literal">exp</code> 函数生成的曲线的图形的演示，请参考 <a class="xref" href="query-dsl-function-score-query.html#exp-decay" title="Exponential decay, keyword exp">指数衰减，关键字 <code class="literal">exp</code></a>。</p>
</dd>
<dt>
<span class="term">
<code class="literal">linear</code>
</span>
</dt>
<dd>
<p>线性衰减，计算如下:</p>
<p><span class="image"><img src="../static/images/Linear.png" alt="Linear"></span>.</p>
<p>
其中，参数 <code class="literal">s</code> 再次被计算以确保分数在距离 <code class="literal">origin</code>+-<code class="literal">offset</code> 的 <code class="literal">scale</code> 距离处取值为 <code class="literal">decay</code>：
</p>
<p><span class="image"><img src="../static/images/s_calc.png" alt="s calc"></span></p>
<p>
与正态和指数衰减相反，如果字段值超过用户给定 scale 值的两倍，此函数实际上将分数设置为0。
</p>
</dd>
</dl>
</div>
<p>
对于单个函数，三个衰减函数以及它们的参数可以像下面这样可视化(在这个例子中称为 “age”<span class="remark">(年龄)</span> 的字段):
</p>
<p><span class="image"><img src="../static/images/decay_2d.png" alt="decay 2d" width="600"></span></p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="_multi_values_fields"></a>多值字段 (multi-values fields)
</h4>
</div></div></div>
<p>
如果用于计算衰减的字段包含多个值，默认情况下会选择最接近原点(origin)的值来确定距离。

这可以通过设置 <code class="literal">multi_value_mode</code> 来改变。
</p>
<div class="informaltable">
<table border="0" cellpadding="4px">
<colgroup>
<col>
<col>
</colgroup>
<tbody valign="top">
<tr>
<td valign="top">
<p>
<code class="literal">min</code>
</p>
</td>
<td valign="top">
<p>
取最小距离作为距离值
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">max</code>
</p>
</td>
<td valign="top">
<p>
取最大距离作为距离值
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">avg</code>
</p>
</td>
<td valign="top">
<p>
取平均距离作为距离值
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">sum</code>
</p>
</td>
<td valign="top">
<p>
取所有距离的和作为距离值
</p>
</td>
</tr>
</tbody>
</table>
</div>
<p>示例：</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">    "DECAY_FUNCTION": {
        "FIELD_NAME": {
              "origin": ...,
              "scale": ...
        },
        "multi_value_mode": "avg"
    }</pre>
</div>
</div>

</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_detailed_example"></a>详细示例
</h3>
</div></div></div>
<p>
假如你正在某个城市寻找一家酒店，而你的预算有限。

此外，你希望酒店靠近市中心，因此酒店离理想位置越远，入住的可能性就越小。
</p>
<p>
你希望匹配你的标准(例如，“hotel, Nancy, non-smoker”)的查询结果根据到市中心的距离以及价格进行评分。
</p>
<p>
直觉上，你可能希望将市中心定义为起点，并且可能愿意从酒店步行 2km 到市中心。
<br>
在这种情况下，位置字段的 <span class="strong strong"><strong>origin</strong></span> 是城镇中心，<span class="strong strong"><strong>scale</strong></span> 为 2km。
</p>
<p>
如果你的预算很低，你可能更喜欢便宜的东西而不是贵的东西。

对于 price(价格) 字段， <span class="strong strong"><strong>origin</strong></span> 为 0 欧元，<span class="strong strong"><strong>scale</strong></span> 取决于你愿意支付的金额，例如 20 欧元。
</p>
<p>
在本例中，对于酒店的价格，字段可能被称为 "price"，而对于该酒店的坐标，字段可能被称为 "location"。
</p>
<p>
在这种情况下， <code class="literal">price</code> 的函数是：
</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"gauss": { <a id="CO40-1"></a><i class="conum" data-value="1"></i>
    "price": {
          "origin": "0",
          "scale": "20"
    }
}</pre>
</div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO40-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>
这个衰减函数也可以是 <code class="literal">linear</code> 或 <code class="literal">exp</code>。
</p>
</td>
</tr>
</table>
</div>
<p>对于 <code class="literal">location</code>：</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"gauss": { <a id="CO41-1"></a><i class="conum" data-value="1"></i>
    "location": {
          "origin": "11, 12",
          "scale": "2km"
    }
}</pre>
</div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO41-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>
这个衰减函数也可以是 <code class="literal">linear</code> 或 <code class="literal">exp</code>。
</p>
</td>
</tr>
</table>
</div>
<p>
假设你想将这两个函数在原始分数上相乘，则请求如下所示：
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "query": {
        "function_score": {
          "functions": [
            {
              "gauss": {
                "price": {
                  "origin": "0",
                  "scale": "20"
                }
              }
            },
            {
              "gauss": {
                "location": {
                  "origin": "11, 12",
                  "scale": "2km"
                }
              }
            }
          ],
          "query": {
            "match": {
              "properties": "balcony"
            }
          },
          "score_mode": "multiply"
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/107.console"></div>
<p>
接下来，我们展示了三种可能的衰减函数的计算分数。
</p>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="gauss-decay"></a>正态衰减，关键字 <code class="literal">gauss</code>
</h4>
</div></div></div>
<p>
在上面的示例中，当选择 <code class="literal">gauss</code> 作为衰减函数时，乘数的等高线和曲面图如下所示:
</p>
<div class="imageblock">
<div class="content">
<img src="../static/images/f.cloud.github.com/assets/4320215/768157/cd0e18a6-e898-11e2-9b3c-f0145078bd6f.png" alt="cd0e18a6 e898 11e2 9b3c f0145078bd6f" width="700px">
</div>
</div>
<div class="imageblock">
<div class="content">
<img src="../static/images/f.cloud.github.com/assets/4320215/768160/ec43c928-e898-11e2-8e0d-f3c4519dbd89.png" alt="ec43c928 e898 11e2 8e0d f3c4519dbd89" width="700px">
</div>
</div>
<p>假设原始搜索结果匹配三家酒店：</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
"Backback Nap"
</li>
<li class="listitem">
"Drink n Drive"
</li>
<li class="listitem">
"BnB Bellevue"
</li>
</ul>
</div>
<p>
"Drink n Drive" 离你定义的位置相当远(将近 2km)，而且不太便宜(约 13 欧元)，所以它的因子很低，为 0.56。

"BnB Bellevue"和"Backback Nap"都非常接近定义的位置，但"BnB Bellevue"更便宜，因此它的因子为 0.86，而"Backpack Nap"的因子值为 0.66。
</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="exp-decay"></a>指数衰减，关键字 <code class="literal">exp</code>
</h4>
</div></div></div>
<p>
在上面的示例中，当选择 <code class="literal">exp</code> 作为衰减函数时，乘数的等高线和曲面图如下所示:
</p>
<div class="imageblock">
<div class="content">
<img src="../static/images/f.cloud.github.com/assets/4320215/768161/082975c0-e899-11e2-86f7-174c3a729d64.png" alt="082975c0 e899 11e2 86f7 174c3a729d64" width="700px">
</div>
</div>
<div class="imageblock">
<div class="content">
<img src="../static/images/f.cloud.github.com/assets/4320215/768162/0b606884-e899-11e2-907b-aefc77eefef6.png" alt="0b606884 e899 11e2 907b aefc77eefef6" width="700px">
</div>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="linear-decay"></a>线性衰减，关键字 <code class="literal">linear</code>
</h4>
</div></div></div>
<p>
在上面的示例中，当选择 <code class="literal">linear</code> 作为衰减函数时，乘数的等高线和曲面图如下所示:
</p>
<div class="imageblock">
<div class="content">
<img src="../static/images/f.cloud.github.com/assets/4320215/768164/1775b0ca-e899-11e2-9f4a-776b406305c6.png" alt="1775b0ca e899 11e2 9f4a 776b406305c6" width="700px">
</div>
</div>
<div class="imageblock">
<div class="content">
<img src="../static/images/f.cloud.github.com/assets/4320215/768165/19d8b1aa-e899-11e2-91bc-6b0553e8d722.png" alt="19d8b1aa e899 11e2 91bc 6b0553e8d722" width="700px">
</div>
</div>
</div>

</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_supported_fields_for_decay_functions"></a>衰减函数支持的字段
</h3>
</div></div></div>
<p>
只支持 numeric、date 和 geo-point 字段。
</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_what_if_a_field_is_missing"></a>如果一个字段缺失，怎么办？
</h3>
</div></div></div>
<p>
如果文档中缺少 numeric 字段，该函数将返回 1。
</p>
</div>

</div>
<div class="navfooter">
<span class="prev">
<a href="query-dsl-dis-max-query.html">« dis_max 查询</a>
</span>
<span class="next">
<a href="full-text-queries.html">全文查询 »</a>
</span>
</div>
</div>

                  <!-- end body -->
                        </div>
                        <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                        
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </section>
</div>
<script src="../static/cn.js"></script>
</body>
</html>